/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.pod.DAO;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.FlushModeType;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Persistence;
import javax.persistence.Query;

/**
 *
 * @author Clenildo Notebook
 */
public class GenericDAO<T> {
    protected EntityManager manager;
	
	protected GenericDAO(){
		manager = getManager();
	}
	
	protected EntityManager getManager(){
		if(manager == null || !manager.isOpen()){
			EntityManagerFactory factory = Persistence.createEntityManagerFactory("ProdutoWebPU");
			manager  = factory.createEntityManager();
			manager.setFlushMode(FlushModeType.COMMIT);
		}
		return manager;
	}
	
	public void begin(){
		if(!getManager().getTransaction().isActive())
			getManager().getTransaction().begin();
	}
	
	public void close(){
		if(getManager().isOpen())
			getManager().close();
	}
	
	public void persist(T obj){
		getManager().persist(obj);
	}
	
	public void remove(T obj){
		getManager().remove(obj);
	}
	
	public T merge(T obj){
		return getManager().merge(obj);
	}
	
	public void refresh(T obj){
		getManager().refresh(obj);
	}
	
	public void flush(){
		getManager().flush();
	}
	
	public void clear(){
		getManager().clear();
	}
	
	public void commit(){
		if(getManager().getTransaction().isActive())
			getManager().getTransaction().commit();
	}
	
	public void rollback(){
		if(getManager().getTransaction().isActive())
			getManager().getTransaction().rollback();
	}
	
	@SuppressWarnings("unchecked")
	public T find(Object chave){
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		return getManager().find(type, chave);
	}
	
	@SuppressWarnings("unchecked")
	public List<T> findAll(){
		Class<T> type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		Query query = getManager().createQuery("select x from " + type.getSimpleName() + " x");
		return (List<T>) query.getResultList();
	}
	
	//---------------------******-----------------//
	
	public Object findByQuery(String consulta){
		try{
			Query query = getManager().createQuery(consulta);
			return query.getSingleResult();
		}
		catch(NoResultException e){
			return null;
		}
		catch(NonUniqueResultException e){
			return null;
		}
	}
	
	@SuppressWarnings("rawtypes")
	public List findAllByQuery(String consulta){
		try{
			Query query = getManager().createQuery(consulta);
			return query.getResultList();
		}
		catch(NoResultException e){
			return null;
		}
		catch(NonUniqueResultException e){
			return null;
		}
	}
	
	public Object findByQueryNativa(String consulta){
		Query query = getManager().createQuery(consulta);
		return query.getSingleResult();
	}
	
	@SuppressWarnings("rawtypes")
	public List findAllByQueryNativa(String consulta){
		Query query = getManager().createQuery(consulta);
		return query.getResultList();
	}
}
